package com.lijing.kmp;

/**
 * @Description TODO
 * @title: KmpAlgorithm
 * @Author LiJing
 * @Date: 2021/4/110:59 下午
 * @Version 1.0
 */
public class KmpAlgorithm {
    public static void main(String[] args) {
        String str1 = "BBC ABCDAB ABCDABCDABDE";
        String str2 = "ABCDABD";
        int index = kmpSearch(str1,str2,kmpNext(str2));
        System.out.println(index);
    }

    public static int kmpSearch(String str1, String str2, int[] next){
        int s1Len = str1.length();
        int s2Len = str2.length();
        for (int i = 0, j = 0; i < s1Len; i++) {
            while (j>0 && str1.charAt(i)!=str2.charAt(j)){
                j = next[j-1];
            }
            if (str1.charAt(i) == str2.charAt(j)){
                j++;
            }
            if (j == s2Len){
                return i-j+1;
            }

        }
        return -1;
    }

    /**
     * 计算next数组
     * @param dest 模式串
     * @return 返回next数组
     * i可理解为后缀的最后一个位置索引
     * j可理解为：①前缀的最后一个位置索引
     *            因为他们从第一个位置开始比较，当对应值相等时意味着前后缀这个串都相等，如果不
     *            相等，j需要回溯，回溯到索引为next[j-1]的位置
     *          ②前后缀能匹配到的长度，因为索引从0开始
     */
    public static int[] kmpNext(String dest){
        int[] next = new int[dest.length()];
        next[0] = 0;
        for (int i = 1, j = 0; i < dest.length(); i++) {
            while (j>0 && dest.charAt(i)!=dest.charAt(j)){
                j = next[j-1];
            }
            if (dest.charAt(i) == dest.charAt(j)){
                j++;
            }
            next[i] = j;
        }
        return next;
    }
}
